import os
from datetime import date, timedelta
from typing import List, Optional
from pathlib import Path
from dataclasses import dataclass
from typing import Optional
import inspect


@dataclass
class WeekReporterFileInfo:
    """
    周报表，是要到的file的信息
    """
    # 本周文件
    this_week_futu_account: Optional[Path] = None
    this_week_futu_position: Optional[Path] = None
    this_week_em_normal: Optional[Path] = None
    this_week_em_credit: Optional[Path] = None
    this_week_em_option: Optional[Path] = None
    this_week_ext: Optional[Path] = None

    # 上周文件
    last_week_futu_account: Optional[Path] = None
    last_week_futu_position: Optional[Path] = None
    last_week_em_normal: Optional[Path] = None
    last_week_em_credit: Optional[Path] = None
    last_week_em_option: Optional[Path] = None
    last_week_ext: Optional[Path] = None

    def __repr__(self):
        attrs = ', '.join(f"{k}={v!r}" for k, v in vars(self).items())
        return f"{self.__class__.__name__}({attrs})"

    def check(self) -> bool:
        """检查所有字段是否非空，返回布尔值"""
        # 定义可选字段（可以为None）
        optional_fields = ['this_week_em_credit', 'this_week_em_option', 'last_week_em_credit', 'last_week_em_option']
        
        for name, value in vars(self).items():
            # if not isinstance(value, Path) or not value.exists():  # 检查Path对象有效性
            #     raise ValueError(f"字段 {name} 必须为有效文件路径且不能为空")
            if name not in optional_fields and value is None:  # 明确检查None而非依赖Path验证
                raise ValueError(f"字段 {name} 不能为None")
        return True

    # def check(self):
    #     """检查所有字段是否不为None"""
    #     for name, field in self.__dataclass_fields__.items():
    #         value = getattr(self, name)
    #         if value is None:
    #             raise ValueError(f"WeekReporterFileInfo.{name} is null")


# # 使用示例
# if __name__ == "__main__":
#     file_info = WeekReporterFileInfo(
#         this_week_futu_account=Path("/path/to/this_week_futu_account.csv"),
#         this_week_futu_position=Path("/path/to/this_week_futu_position.csv"),
#         this_week_em_normal=Path("/path/to/this_week_em_normal.csv"),
#         this_week_em_credit=Path("/path/to/this_week_em_credit.csv"),
#         this_week_em_option=Path("/path/to/this_week_em_option.csv"),
#         this_week_ext=Path("/path/to/this_week_ext.csv"),
#         last_week_futu_account=Path("/path/to/last_week_futu_account.csv"),
#         last_week_futu_position=Path("/path/to/last_week_futu_position.csv"),
#         last_week_em_normal=Path("/path/to/last_week_em_normal.csv"),
#         last_week_em_credit=Path("/path/to/last_week_em_credit.csv"),
#         last_week_em_option=Path("/path/to/last_week_em_option.csv"),
#         last_week_ext=Path("/path/to/last_week_ext.csv")
#     )
#
#     try:
#         file_info.check()
#         print("All files are valid")
#     except ValueError as e:
#         print(f"Validation error: {e}")
#

class WeekReporterFilePicker:
    def __init__(self):
        # 富途文件目录
        self.futu_dir = "D:\\work\\other_side_happiness\\futu"
        # 东方财富文件目录
        self.em_dir = "D:\\work\\other_side_happiness\\dfcf\\持仓"
        # 扩展信息文件目录
        self.ext_dir = "D:\\work\\other_side_happiness\\report\\ext"

    def pick(self, shift: int = 0) -> WeekReporterFileInfo:
        """
        Args:
            shift: 向前偏移的周数（默认0表示当前周）

        挑选本周和上周的相关文件信息
        :return: 周报表文件信息对象
        """
        ret = WeekReporterFileInfo()
        weekend_dates = self.get_weekends(shift)
        print(f"weekendDates: {weekend_dates}")

        # futu 持仓
        this_week_futu = self.find_files_by_keywords(
            self.futu_dir,
            [
                f"保证金综合账户(9257)-{weekend_dates[0].strftime('%Y.%m.%d')}",
                f"保证金综合账户(9257)-{weekend_dates[1].strftime('%Y.%m.%d')}"
            ],
            ["csv"]
        )
        assert len(this_week_futu) == 1
        ret.this_week_futu_position = this_week_futu[0]

        last_week_futu = self.find_files_by_keywords(
            self.futu_dir,
            [
                f"保证金综合账户(9257)-{weekend_dates[2].strftime('%Y.%m.%d')}",
                f"保证金综合账户(9257)-{weekend_dates[3].strftime('%Y.%m.%d')}"
            ],
            ["csv"]
        )
        if last_week_futu:
            assert len(last_week_futu) == 1
            ret.last_week_futu_position = last_week_futu[0]

        # 富途账户文件
        this_week_futu = self.find_files_by_keywords(
            self.futu_dir,
            [
                f"{weekend_dates[0].strftime('%Y%m%d')}futu_account",
                f"{weekend_dates[1].strftime('%Y%m%d')}futu_account"
            ],
            ["csv"]
        )
        assert len(this_week_futu) == 1
        ret.this_week_futu_account = this_week_futu[0]

        last_week_futu = self.find_files_by_keywords(
            self.futu_dir,
            [
                f"{weekend_dates[2].strftime('%Y%m%d')}futu_account",
                f"{weekend_dates[3].strftime('%Y%m%d')}futu_account"
            ],
            ["csv"]
        )
        if last_week_futu:
            assert len(last_week_futu) == 1
            ret.last_week_futu_account = last_week_futu[0]

        # 东财普通账户文件
        this_week_em_normal = self.find_files_by_keywords(
            self.em_dir,
            [
                f"{weekend_dates[0].strftime('%Y%m%d')}_pt",
                f"{weekend_dates[1].strftime('%Y%m%d')}_pt"
            ],
            ["txt"]
        )
        if this_week_em_normal:
            assert len(this_week_em_normal) == 1
            ret.this_week_em_normal = this_week_em_normal[0]

        last_week_em_normal = self.find_files_by_keywords(
            self.em_dir,
            [
                f"{weekend_dates[2].strftime('%Y%m%d')}_pt",
                f"{weekend_dates[3].strftime('%Y%m%d')}_pt"
            ],
            ["txt"]
        )
        if last_week_em_normal:
            assert len(last_week_em_normal) == 1
            ret.last_week_em_normal = last_week_em_normal[0]

        # 东财信用账户文件
        this_week_em_credit = self.find_files_by_keywords(
            self.em_dir,
            [
                f"{weekend_dates[0].strftime('%Y%m%d')}_xy",
                f"{weekend_dates[1].strftime('%Y%m%d')}_xy"
            ],
            ["txt"]
        )
        if this_week_em_credit:
            assert len(this_week_em_credit) == 1
            ret.this_week_em_credit = this_week_em_credit[0]

        last_week_em_credit = self.find_files_by_keywords(
            self.em_dir,
            [
                f"{weekend_dates[2].strftime('%Y%m%d')}_xy",
                f"{weekend_dates[3].strftime('%Y%m%d')}_xy"
            ],
            ["txt"]
        )
        if last_week_em_credit:
            assert len(last_week_em_credit) == 1
            ret.last_week_em_credit = last_week_em_credit[0]

        # 东财期权账户文件
        this_week_em_option = self.find_files_by_keywords(
            self.em_dir,
            [
                f"{weekend_dates[0].strftime('%Y%m%d')}_qq",
                f"{weekend_dates[1].strftime('%Y%m%d')}_qq"
            ],
            ["txt"]
        )
        if this_week_em_option:
            assert len(this_week_em_option) == 1
            ret.this_week_em_option = this_week_em_option[0]

        last_week_em_option = self.find_files_by_keywords(
            self.em_dir,
            [
                f"{weekend_dates[2].strftime('%Y%m%d')}_qq",
                f"{weekend_dates[3].strftime('%Y%m%d')}_qq"
            ],
            ["txt"]
        )
        if last_week_em_option:
            assert len(last_week_em_option) == 1
            ret.last_week_em_option = last_week_em_option[0]

        # 扩展信息文件
        this_week_ext = self.find_files_by_keywords(
            self.ext_dir,
            [
                weekend_dates[0].strftime('%Y%m%d'),
                weekend_dates[1].strftime('%Y%m%d')
            ],
            ["csv"]
        )
        if this_week_ext:
            assert len(this_week_ext) == 1
            ret.this_week_ext = this_week_ext[0]

        last_week_ext = self.find_files_by_keywords(
            self.ext_dir,
            [
                weekend_dates[2].strftime('%Y%m%d'),
                weekend_dates[3].strftime('%Y%m%d')
            ],
            ["csv"]
        )
        if last_week_ext:
            assert len(last_week_ext) == 1
            ret.last_week_ext = last_week_ext[0]

        return ret

    def find_files_by_keywords(self, folder_path: str, keywords: List[str], extensions: List[str]) -> List[str]:
        """
        在指定文件夹下查找文件名包含任意关键字且符合后缀的文件
        :param folder_path: 文件夹路径
        :param keywords: 关键字数组（匹配任意一个即可）
        :param extensions: 文件后缀数组（如："txt", "jpg"，不包含点；None表示不限制后缀）
        :return: 匹配的文件列表
        """
        result = []
        if not os.path.exists(folder_path) or not os.path.isdir(folder_path):
            print(f"错误：文件夹不存在或不是有效目录 - {folder_path}")
            return result

        for root, dirs, files in os.walk(folder_path):
            for file in files:
                file_name = os.path.join(root, file)
                if (any(keyword in file.lower() for keyword in keywords) and
                        (extensions is None or any(file.lower().endswith(f".{ext}") for ext in extensions))):
                    result.append(file_name)

        return result

    def get_weekends(self, shift: int = 0) -> List[date]:
        """
        获取指定周和上一周的周六和周日日期

        Args:
            shift: 向前偏移的周数（默认0表示当前周）

        Returns:
            包含四个日期的列表，顺序为：
            - 指定周周六
            - 指定周周日
            - 上一周周六
            - 上一周周日
        """
        today = date.today()

        # 计算指定周的周六和周日
        specified_week_saturday = today + timedelta(days=(5 - today.weekday()) - shift * 7)
        specified_week_sunday = today + timedelta(days=(6 - today.weekday()) - shift * 7)

        # 计算上一周的周六和周日
        previous_week_saturday = specified_week_saturday - timedelta(days=7)
        previous_week_sunday = specified_week_sunday - timedelta(days=7)

        return [
            specified_week_saturday,
            specified_week_sunday,
            previous_week_saturday,
            previous_week_sunday
        ]
if __name__ == '__main__':
    picker = WeekReporterFilePicker()

    fileInfo = picker.pick(shift=1)
    print(f"{fileInfo}")